package cn.catsdad.util;

import cn.catsdad.vo.TreeNodeVO;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 树形工具
 *
 * @author xuyonglong
 * @version V1.0 2023/4/21
 */
public class TreeUtil {

    public static enum Sort {
        ASC,
        DESC
    }

    /**
     * 构建树形
     *
     * @param treeNodeVOList 所有树形节点容器
     * @return 完成构建的树
     */
    public static List<TreeNodeVO> buildTree(List<TreeNodeVO> treeNodeVOList, Sort sort) {
        List<TreeNodeVO> result = buildRootNodes(treeNodeVOList, sort);
        fillingChildren(result, treeNodeVOList, sort);
        return result;
    }

    /**
     * 构建根节点
     *
     * @param treeNodeVOList 所有节点容器
     * @return 根节点结构
     */
    private static List<TreeNodeVO> buildRootNodes(List<TreeNodeVO> treeNodeVOList, Sort sort) {
        List<TreeNodeVO> result = new ArrayList<>();
        for (TreeNodeVO treeNodeVo : treeNodeVOList) {
            if (treeNodeVo.getParentId() == null) {
                result.add(treeNodeVo);
            } else {
                Optional<TreeNodeVO> parent = treeNodeVOList.stream().filter(n -> treeNodeVo.getParentId().equals(n.getId())).findFirst();
                if (!parent.isPresent()) {
                    result.add(treeNodeVo);
                }
            }
        }
        return sort(result, sort);
    }

    private static List<TreeNodeVO> sort(Collection<TreeNodeVO> collection, Sort sort) {
        List<TreeNodeVO> result = new ArrayList<>(collection.size());
        if (StringUtil.isNotEmpty(collection)) {
            if (Sort.ASC.equals(sort)) {
                result = collection.stream().sorted(Comparator.comparing(TreeNodeVO::getOrderNum)).collect(Collectors.toList());
            } else {
                result = collection.stream().sorted(Comparator.comparing(TreeNodeVO::getOrderNum, Comparator.reverseOrder())).collect(Collectors.toList());
            }
        }
        return result;
    }

    /**
     * 子节点构建
     *
     * @param parents      父节点容器
     * @param allTreeNodes 所有节点容器
     */
    private static void fillingChildren(List<TreeNodeVO> parents, List<TreeNodeVO> allTreeNodes, Sort sort) {
        for (TreeNodeVO parent : parents) {
            List<TreeNodeVO> children = allTreeNodes.stream()
                    .filter(n -> parent.getId().equals(n.getParentId()))
                    .sorted(Comparator.comparing(TreeNodeVO::getOrderNum, Comparator.reverseOrder()))
                    .collect(Collectors.toList());
            if (StringUtil.isNotEmpty(children)) {
                fillingChildren(children, allTreeNodes, sort);
            }
            parent.setChildren(sort(children, sort));
        }
    }

}
